<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>vue实现简单拖拽</title>
    <style>
        html,body,.content{
            width:100%;
            height:100%;
            overflow: hidden;
        }
        .rect,.rect div{
            width:100px;
            height:100px;
            overflow: hidden;
            cursor: pointer;
            position:absolute;
            top:0;
            left:0;
        }
        .borderBg{
            border:1px dashed rgb(51, 3, 3);
        }
        .bgHighLight{
            opacity: 0.4;
        }
        .dragTips{
            float:right;
            font-size:30px;
            margin:5%;
        }
    </style>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>

<body>

    
    <!--要把draggable属性设为true才能允许拖拽 -->
    <div id="content" class="content" @dragenter.stop="dragenter($event)" @dragover.stop.prevent="dragover($event)"
    @dragleave.stop="dragleave($event)" @drop.stop="drop($event)" style="">
    
        <span class="dragTips">拖动一个试试看！</span>

        <div v-for="(v, index) in list" class="rect rect1" :class="{'borderBg':v.focus, 'bgHighLight':v.focus}" :draggable="draggable" @dragstart.stop="dragstart($event, v)"
            @dragend.stop.prevent="dragend($event, v)" @drag.stop="drag($event, v)" :style="{'background':v.color, 'left':v.x +'px', 'top':v.y + 'px', 'width':v.w +'px', 'height':v.h + 'px', 'z-index':v.zIndex}"></div>
    </div>

    <script src="../date/Utils.js"></script>
    <script>
        var drag = new Vue({
            el: "#content",
            data: {
                draggable:true, //是否可以拖拽
                thisDrag:null,  //当前拖动元素
                x:null, //拖动目标位置x轴
                y:null, //拖动目标位置y轴
                m_clientX:null, //鼠标在当前元素的X偏移值，为了防止拖拽时中心点不是左上角造成的偏离值
                m_clientY:null, //鼠标在当前元素的Y偏移值
                timer:null, //动画定时器
                list:[],    //方块数据
            },
            mounted() {
                //方块初始化
                this.init();
            },
            methods: {
                //方块初始化
                init(){
                    let arr = [];
                    for(let a=0;a<10;a++){
                        arr.push({
                            id:a,
                            color:`rgb(${utils.randomNum(0,255)},${utils.randomNum(0,255)},${utils.randomNum(0,255)})`,
                            x:a * a * 2,
                            y:a * a * 2,
                            w:a * 25,
                            h:a * 25,
                            zIndex:a,   //层级
                            drag:true,  //是否可拖拽
                            focus:false,    //是否选中，并拖拽中
                        });
                    }
                    this.list = arr;
                },
                //回调函数——在元素开始被拖动时
                dragstart(ev, obj) {

                    //兼容IE
                    var ev = ev || window.event;

                    //兼容火狐
                    if (navigator.userAgent.indexOf('Firefox') >= 0) {
                        ev.dataTransfer = ev.originalEvent.dataTransfer;
                        //设置要写入的信息
                        ev.dataTransfer.setData('test', "test");
                    }

                    //用于在拖放操作过程中，修改鼠标指针所指向的图像，未生效……
                    //ev.dataTransfer.setDragImage(this.$refs.img1, 0, 0);

                    //获取拖放时要写入的信息
                    let dt = ev.dataTransfer;

                    //设定effectAllowed属性形式为 copy 复制
                    dt.effectAllowed = 'copy';

                    //设置要写入的信息
                    dt.setData("text/html", ev.target.outerHTML);

                    //保存拖动元素
                    this.thisDrag = obj;

                    //更新鼠标在当前元素位置
                    this.m_clientX = ev.clientX-ev.target.offsetLeft;
                    this.m_clientY = ev.clientY-ev.target.offsetTop;

                    //更新拖动元素样式
                    this.thisDrag.focus = true;
                    //拖动闪动效果
                    this.timerAnimation(0.5);

                },
                //回调函数——在元素被拖动时触发
                drag(ev, obj) {

                    //兼容IE
                    var ev = ev || window.event;

                    console.log("元素被拖动中，只要不松手此事件一直会触发");

                },
                //回调函数——在拖动操作完成时
                dragend(ev, obj) {

                    //兼容IE
                    var ev = ev || window.event;

                    //兼容火狐
                    if (navigator.userAgent.indexOf('Firefox') >= 0) {
                        ev.dataTransfer = ev.originalEvent.dataTransfer;
                        //设置要写入的信息
                        ev.dataTransfer.setData('test');
                    }

                    //更新目标位置
                    if(this.thisDrag){
                        this.thisDrag.x = this.x;
                        this.thisDrag.y = this.y;
                        //设置层级
                        this.setZIndex();
                    }
                    //更新拖动元素样式
                    this.thisDrag.focus = false;
                    //停止拖动闪动效果
                    this.timerAnimationStop();
                },
                //回调函数——当被拖动元素在释放区内移动时
                dragover(ev) {

                    //兼容IE
                    var ev = ev || window.event;

                    //获取拖放时要写入的信息
                    let dt = ev.dataTransfer;

                    //更新目标位置
                    this.x = ev.clientX - this.m_clientX;
                    this.y = ev.clientY - this.m_clientY;

                    dt.dropEffect = 'copy';   //拷贝被拖拽div，实现拖拽预览位置

                    return false;

                },
                //回调函数——当被拖动元素在释放区里放下时
                drop(ev) {

                    //兼容IE
                    var ev = ev || window.event;

                    //从DataTransfer对象那里获取要写入的信息
                    let dt = ev.dataTransfer;
                    //获取要写入的信息
                    let html = dt.getData("text/html");

                    //通过设置textContent属性的支，可以输出纯文本形式
                    //this.dragTarget.textContent += text;   

                    console.log("拖动完成");

                },
                //回调函数——被拖动元素进入到释放区所占据得屏幕空间时
                dragenter(ev) {

                    //兼容IE
                    var ev = ev || window.event;

                    console.log("现在开始拖拽中，每次在目标区域内移动都会触发此事件");

                },
                //回调函数——当被拖动元素没有放下就离开释放区时
                dragleave(ev) {

                    //兼容IE
                    var ev = ev || window.event;

                    console.log("现在已离开目标区域");

                },
                //拖动闪动效果
                timerAnimation(step){   //step 间隔秒数
                    this.thisDrag.focus = true;
                    this.timer = setInterval(() => {
                        this.thisDrag.focus?this.thisDrag.focus = false:this.thisDrag.focus = true;
                    }, step * 1000);
                },
                //停止拖动闪动效果
                timerAnimationStop(){
                    clearInterval(this.timer);
                    this.thisDrag.focus = false;
                },
                //设置层级
                setZIndex(){
                    let max = this.list.sort((a, b) => {
                        return b.zIndex - a.zIndex;
                    })[0].zIndex;
                    this.thisDrag.zIndex = max+1;
                }
            }
        });
    </script>
</body>

</html>